package cn.ruc.dbiir.neo4j;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

import org.neo4j.graphalgo.GraphAlgoFactory;
import org.neo4j.graphalgo.PathFinder;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.PathExpanders;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.graphdb.traversal.Evaluators;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.procedure.Name;


public class WhereUsed {
	
	public static void main(String[] args) {
		try {
			where_used3();
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}
	
	private enum RelTypes implements RelationshipType{
        rel,
    }
	
	private enum LableTypes implements Label{
		item,
	}
	
	public static Stream<UsedPart> where_used3() throws Throwable {
		
		GraphDatabaseService graphDb = new GraphDatabaseFactory().
				newEmbeddedDatabase(new File("/Users/mark/Documents/MasterLife/GraphDB/neo4j-community-3.4.6/data/databases/test2.db"));
		registerShutdownHook( graphDb );
		Transaction tx = graphDb.beginTx();
		
		int lev = (int) 2;
		RelationshipType rtp = RelTypes.rel;
		Label lt = LableTypes.item;

		TraversalDescription td = graphDb.traversalDescription() //定义一个遍历方法
				.depthFirst()
				.relationships( rtp, Direction.INCOMING )
				.evaluator( Evaluators.excludeStartPosition() )
				.evaluator( Evaluators.toDepth( lev ) );

		PathFinder<Path> finder = GraphAlgoFactory.shortestPath( 
				PathExpanders.forTypesAndDirections(rtp, Direction.INCOMING, rtp, Direction.INCOMING), 
				lev-1 
				);

		Node node = graphDb.findNode( lt, "plm_m_id", "796" ); //寻找传入的节点
		List<UsedPart> results = new ArrayList<UsedPart>();
		Relationship pathrel;
		Node start;
		Node end;

		for(Path childPath: td.traverse(node)) {// 从传入节点开始进行深度优先遍历
//			System.out.println("the number of childPath:"+childPath.length());
			pathrel = childPath.lastRelationship();
			
			start = childPath.startNode();
			end = childPath.endNode();
			System.out.println("startnode:"+start.getProperty("plm_m_oid") + " endnode:"+end.getProperties("plm_m_oid"));
			for(Node nodess:childPath.nodes()) {
				System.out.println(nodess.getProperty("plm_m_oid"));
			}
			String item_path = "796";

			Iterable<Path> paths = finder.findAllPaths(node, end); //获取起始节点和结束节点的所有路径
			for (Path path : paths) {// 统计每个路径的信息
			if(path!=null){
			for (Relationship relationship : path.relationships()) {
			 item_path = item_path + ">" + relationship.getStartNode().getProperty("plm_m_id").toString();
			 System.out.println(item_path);
			}
			}
			
			results.add(new UsedPart(
			end.getProperty("plm_m_id").toString(), 
			start.getProperty("plm_m_id").toString(), 
			start.getProperty("plm_m_oid").toString(), 
			end.getProperty("plm_m_oid").toString(), 
			pathrel.getProperty("plm_oid").toString(), 
			pathrel.getProperty("plm_number").toString(), 
			(long)childPath.length(), 
			item_path
			));
			}
		}
		tx.success();
		 System.out.println("resultsize:"+results.size());
		return results.stream();

	}
	
	private static void registerShutdownHook( final GraphDatabaseService graphDb ) {
		Runtime.getRuntime().addShutdownHook( new Thread()
		{
			@Override
			public void run()
			{
				graphDb.shutdown();
			}
		} );
	}

	public static class UsedPart{
		public String pid;
		public String cid;
		public String poid;
		public String coid;
		public String rel_oid;
		public String cnt;
		public long lev;
		public String path;

		public UsedPart( String pid, String cid, String poid, String coid, String rel_oid, String cnt, long lev, String path ){
			this.pid = pid;
			this.cid = cid;
			this.poid = poid;
			this.coid = coid;
			this.rel_oid = rel_oid;
			this.cnt = cnt;
			this.lev = lev;
			this.path = path;

		}
	}

}

